/*
 * ext2_fs.c
 *
 *  Created on: 29/04/2012
 *      Author: utnso
 */
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include "bloques.h"
#include "constants.h"
#include "ext2_types.h"
#include "ext2_fs.h"



ext2_super_block *readSuperBlock(void *address){
	ext2_super_block *super_block = (ext2_super_block *)malloc(sizeof(ext2_super_block));
	memcpy(super_block, (ext2_super_block *)address + 1, sizeof(ext2_super_block));

	//TODO: Hay que comprobar el s_magic para que el filesystem corresponda a ext2

	return super_block;
}

ext2_group_desc *readGroupDescriptor(void *address, int groupId){
	ext2_group_desc *group_desc = (ext2_group_desc *)malloc(sizeof(ext2_group_desc));
	void *start_address = address + BLOCK_SIZE * 2; //Descriptors always begin after super_blocks
	memcpy(group_desc, (ext2_group_desc *)start_address + groupId, sizeof(ext2_group_desc));

    return group_desc;

}

ext2_inode * leerTablaInodos(void *address, int groupId){
	ext2_super_block *super_block = readSuperBlock(address);
	ext2_group_desc *group_desc = readGroupDescriptor(address, groupId);
	ext2_inode *tablaInodos = (ext2_inode*)malloc(INODES_TABLE_SIZE(super_block));
	void *start_address = address + BLOCK_SIZE * group_desc->bg_inode_table;
	memcpy(tablaInodos, start_address, INODES_TABLE_SIZE(super_block));

	free(group_desc);
	free(super_block);
	return tablaInodos;
}

ext2_inode * leerInodo(void *address, int numInodo){
	// TODO: REHACER. MAXI TIENE QUE EXPLICAR ARITMETICA DE PUNTEROS.
	ext2_super_block *super_block = readSuperBlock(address);

	//Busco en que grupo de bloque se encuentra el inodo
	int groupId =0;
	if(numInodo<=EXT2_INODES_PER_GROUP(super_block)){
		groupId = 0;
	}
	else{
		groupId = 1;
		int limiteInferior =  groupId * EXT2_INODES_PER_GROUP(super_block);
		int limiteSuperior =  (groupId + 1) * EXT2_INODES_PER_GROUP(super_block);

		while(!((numInodo > limiteInferior) && (numInodo  <= limiteSuperior))){
			groupId++;
		}
	}

	//Calculo la posicion dentro de la tabla de inodos del grupo
	int posInodo = numInodo - (groupId * EXT2_INODES_PER_GROUP(super_block));
	ext2_group_desc *group_desc = readGroupDescriptor(address, groupId);
	ext2_inode *inodo = (ext2_inode*)malloc(EXT2_INODE_SIZE(super_block));
	void *start_address = address + BLOCK_SIZE * group_desc->bg_inode_table
			+ ((posInodo - 1) * EXT2_INODE_SIZE(super_block));

	memcpy(inodo, start_address, EXT2_INODE_SIZE(super_block));

	free(group_desc);
	free(super_block);
	return inodo;
}
